﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using Beaker.Injection;
using Moq;

namespace OpenCube.Specs
{
	public sealed class InjectionConfigurationValidator
	{
		private readonly List<Type> _injectionModules = new List<Type>();
		private readonly List<Type> _interfaceTypes = new List<Type>(); 

		public InjectionConfigurationValidator ScanAssemblyContaining<TModule>()
			where TModule : IInjectionModule
		{
			_injectionModules.AddRange(
				from type in typeof(TModule).Assembly.GetTypes()
				where typeof(IInjectionModule).IsAssignableFrom(type)
				where type.IsClass && !type.IsAbstract
				where type.GetConstructor(Type.EmptyTypes) != null
				select type);

			_interfaceTypes.AddRange(
				from type in typeof(TModule).Assembly.GetTypes()
				where type.IsInterface
				select type);

			return this;
		}

		public IInjectionValidationResult Scan()
		{
			var stub = new InjectionContainerBuilderStub(_interfaceTypes);

			foreach (Type modeleType in _injectionModules)
			{
				var module = (IInjectionModule)Activator.CreateInstance(modeleType);
				module.Register(stub);
			}

			return stub;
		}
	}
}
